import React, { Component } from 'react'
import {
    Card,
    Form,
    Input,
    Cascader,
    Button,
    message
} from "antd"
import { ArrowLeftOutlined } from "@ant-design/icons"
import LinkButton from '../../components/link-button';
import { reqGetCategorys,reqAddOrUpdateProduct } from "../../api/index"
import PicturesWall from './PicturesWall';
import RichTextEditor from './RichTextEditor'; 

const {Item} = Form;
const { TextArea } = Input;


/*
    添加和更新的子路由组件
 */
export default class ProductAddUpdate extends Component {
    constructor(props) {
        super(props)
        const product = this.props.location.state
        // 保存一个是否是更新的标识
        this.isUpdate = !!product
        // 保存商品 如果没有 保存{}
        this.product = product || {}
    }

    state = {
        optionLists:[] 
    }

    onFinish = async (values) => {
        // 1. 收集数据并封装成product对象
        const{name, desc, price, categoryIds} = values
        let pCategoryId ,categoryId;
        if (categoryIds.length === 1) {
            pCategoryId = "0"
            categoryId = categoryIds[0]
        } else {
            pCategoryId = categoryIds[0]
            categoryId = categoryIds[1]
        }
        const imgs = this.pw.getImgs()
        const detail = this.editor.getDetail()
        const product = {name, desc, price, imgs, detail, pCategoryId, categoryId}

        if(this.isUpdate) {
            product._id = this.product._id
        }
        // 2. 调用接口函数去添加/ 更新'
        const result = await reqAddOrUpdateProduct(product)
        // 3. 根据结果显示
        if(result.status === 0) {
            message.success(`${this.isUpdate ? "更新" : "添加"}商品成功`)
            this.props.history.goBack()
        } else {
            message.error(`${this.isUpdate ? "更新" : "添加"}商品失败`)
        }
    };

    onFinishFailed = (errorInfo) => {
        console.log('Failed:', errorInfo);
    };  
    
    

    // 初始化optionLists
    initOptionList = async (categorys) => {
        // 根据categorys生成options数组
        const optionLists = categorys.map(c => ({
            value: c._id,
            label: c.name,
            isLeaf: false, // 不是叶子
        }));

        // 如果是一个二级分类商品的更新
        const {isUpdate, product} = this
        const {pCategoryId} = product
        if(isUpdate && pCategoryId !== "0") {
           // 获取对应的二级分类列表
           const subCategorys = await this.getCategorys(pCategoryId) 
           // 生成二级下拉列表的optionLists
           const childOptions = subCategorys.map(c => ({
                value: c._id,
                label: c.name,
                isLeaf: true,
           }))
           // 找到当前商品对应的一级option对象
           const targetOption = optionLists.find(option => option.value === pCategoryId)
           // 关联到对应的一级optionLists上
           if(targetOption !== undefined) {
            targetOption.children = childOptions
           }
        }


        // 更新optionLists列表
        this.setState({optionLists})
    }
    
    /* 
        获取一级/二级分类列表
        async函数的返回值是一个新的promise对象,promise的结果和值由async的结果来决定 
    */
    getCategorys = async (parentId) => {
        const result = await reqGetCategorys(parentId);
        if(result.status === 0) {
            const categorys = result.data;
            // 如果是一级分类
            if(parentId === "0") {
                this.initOptionList(categorys);
            } // 如果是二级列表
            else {
                return categorys; //返回二级列表 => 当前async函数返回的promise就会成功且value为categorys
            }
            
        }
    }

     

    // 用于加载下一级列表的回调函数
    loadData = async selectedOptions => {
        // 得到选择的option对象
        const targetOption = selectedOptions[0];
        // 显示Loading效果
        targetOption.loading = true;
    

        // 根据请求的分类,请求获取二级列表
        const subCategorys = await this.getCategorys(targetOption.value)
        // 隐藏loading效果
        targetOption.loading = false;
        if(subCategorys && subCategorys.length > 0) {
            // 生成一个二级列表的options
            const childOptionLists = subCategorys.map(c => ({
                value: c._id,
                label: c.name,
                isLeaf: true, // 是叶子
            }))
            // 关联到当前targetOption上
            targetOption.children = childOptionLists
        } else { // 当前选中的分类没有二级分类
            targetOption.isLeaf = true;
        }
        
        // 更新optionLists状态
        this.setState({optionLists:[...this.state.optionLists]});
    };

    componentDidMount() {
        this.getCategorys("0");
    }


    render() {
        // 取出标识和product
        const {isUpdate, product} = this
        const {pCategoryId, categoryId, imgs, detail} = product
        // 用来接受级联分类ID的数组
        const categoryIds = []
        if(isUpdate) {
            // 商品是一级分类商品
            if(pCategoryId === "0") {
                categoryIds.push(categoryId)
            } else { // 商品是二级分类商品
                categoryIds.push(pCategoryId)
                categoryIds.push(categoryId)
            }
            
        }

        // 指定Item布局的配置对象
        const formItemLayout = {
            labelCol: { span: 3 }, // 左侧Label宽度
            wrapperCol: { span: 8 }, // 指定右侧包裹的宽度
        };

        const title = (
            <span>
                <LinkButton onClick={() => this.props.history.goBack()}>
                    <ArrowLeftOutlined/>
                </LinkButton>
                <span>{isUpdate? "更新商品":"添加商品"}</span>
            </span>
        )

        return (
            <Card title={title}>
                <Form 
                    {...formItemLayout}
                    initialValues={{
                        name: product.name,
                        desc: product.desc,
                        price:product.price,
                        categoryIds
                    }}
                    onFinish={this.onFinish}
                    onFinishFailed={this.onFinishFailed}
                >
                    <Item
                        name="name"
                        label="商品名称"
                        rules={[
                            {
                                required:true,
                                message:"商品名称必须输入"
                            }
                        ]}
                    >
                        <Input placeholder="请输入商品名称"/>
                    </Item>
                    <Item
                        name="desc"
                        label="商品描述"
                        rules={[
                            {
                                required:true,
                                message:"商品描述必须输入"
                            }
                        ]}
                    >
                        <TextArea placeholder="请输入商品描述" autoSize={{minRows: 2, maxRows: 6}} />
                    </Item>
                    <Item
                        name="price"
                        label="商品价格"
                        rules={[
                            {
                                required: true,
                                message:"商品价格必须输入"
                            },
                            {
                                validator: (_, value,) => {
                                    if(value * 1 > 0){
                                        return Promise.resolve();
                                    } else {
                                        return Promise.reject("商品价格必须大于0")
                                    }
                                }
                            }
                        ]}
                    >
                        <Input type="number" placeholder="请输入商品价格" addonAfter="元"/>
                    </Item>
                    <Item
                        name="categoryIds"
                        label="商品分类"
                        rules={[
                            {
                                required: true,
                                message: "商品分类必须选择"
                            }
                        ]}
                    >
                        <Cascader
                            placeholder="请指定商品分类"
                            options={this.state.optionLists} // 需要显示的列表数据数组
                            loadData={this.loadData} // 当选择某个列表项,加载下一级列表的监听回调
                        />
                    </Item>
                    <Item
                        label="商品图片"
                    >
                        <PicturesWall ref={c => this.pw = c} imgs={imgs}/>
                    </Item>
                    <Item
                        label="商品详情"
                        labelCol={{span: 3 }}
                        wrapperCol={{ span: 20 }}
                    >
                        <RichTextEditor ref={c => this.editor = c} detail={detail}/>
                    </Item>
                    <Item>
                        <Button type="primary" htmlType="submit">
                            提交
                        </Button>
                    </Item>  
                </Form>
            </Card>
        )
    }
}


/*
    1. 子组件调用父组件的方法: 将父组件的方法以函数属性的形式传递给子组件, 子组件就可以调用
    2. 父组件调用子组件的方法: 通过在父组件中ref得到子组件标签对象(也就是组件对象), 调用其方法 
    */

